home *** CD-ROM | disk | FTP | other *** search
- ###############################################################################
- ###############################################################################
- ##### Dialogos.tcl
- ###############################################################################
- ###############################################################################
- ##### The contents of this file are adapted from an example in Brent Welch's
- ##### book "Practical Programming in Tcl/Tk". I made the changes without
- ##### knowing very well what I was doing, so please, don't blame him for all
- ##### the weirdness.
- ###############################################################################
- ##### Copyright 1999-2003 Brent Welch - AndrΘs Garcφa. fandom@retemail.es
- ##### The contents of this file are distributed under the terms of the LGPL
- ###############################################################################
-
- namespace eval Dialogos {
-
- ###############################################################################
- # SelectDirNative
- # Does the work by using a Windows dialog
- #
- # Parameters:
- # initialDir: The directory in which the dialog will open itself.
- # parent: The window over which it will appear.
- #
- # Returns:
- # The chosen path or an empty string if the user cancels.
- #
- # Side effects:
- # If you select a non-existing directory, it will be created for you.
- ###############################################################################
- proc SelectDirNative {initialDir parent} {
- global labelTitles labelMessages indexButtons
-
- set chosenDir [tk_chooseDirectory -title $labelTitles(directory) \
- -parent $parent -initialdir $initialDir]
-
- if {$chosenDir==""} return
-
- if {![file exist $chosenDir]} {
- set what [tk_messageBox -icon question \
- -message $labelMessages(unknown) -title $labelTitles(unknown)\
- -parent $parent -type yesno]
- if {$what=="no"} {
- set initialDir $chosenDir
- while {![file exists $initialDir]} {
- set initialDir [file dirname $initialDir]
- }
- return [SelectDirWindows $initialDir $parent]
- }
- file mkdir $chosenDir
- }
- return $chosenDir
- }
-
- ###############################################################################
- # SelectDirectory
- # Opens a dialog window which allows the user to choose one directory. If
- # needed, the directory is created.
- #
- # Parameter:
- # initialDir: directory where the dialog should open itself.
- # parent: the parent window of the dialog, it defaults to the main
- # window of the app.
- #
- # Returns
- # The full path of the chosen directory.
- ###############################################################################
- proc SelectDirectory {{initialDir {} } {parent {.} } } {
- variable fileselect
- variable useWinDialog
- global tcl_patchLevel getleftState
- global dirGetleft getleftOptions labelMenus indexButtons
- global env labelButtons labelTitles labelDialogs labelMessages
-
- set useNativeDialog 0
- if {$getleftState(os)!="unix"} {
- set useNativeDialog 1
- }
- if {$useNativeDialog==1} {
- return [SelectDirNative $initialDir $parent]
- }
-
- catch {destroy .fileselect}
- set t [toplevel .fileselect -bd 4]
-
- set coord(x) [winfo rootx $parent]
- set coord(y) [winfo rooty $parent]
-
- wm title $t $labelTitles(directory)
- wm resizable $t 0 0
- wm geometry $t +[expr {$coord(x)+100}]+[expr {$coord(y)+15}]
-
- set fdir [frame $t.directorio]
- set imaArr [image create photo \
- -file [file join "$dirGetleft(icons)" arriba.gif]]
- set imaNew [image create photo \
- -file [file join "$dirGetleft(icons)" nuevo.gif]]
- button $fdir.arriba -image $imaArr -command {
- Dialogos::fileselectList [file dirname $Dialogos::fileselect(dir)]
- Dialogos::fileselectOK
- }
- button $fdir.new -image $imaNew -command ::Dialogos::NewDir
-
- BalloonHelp::set_balloon $fdir.arriba $labelMessages(up)
- BalloonHelp::set_balloon $fdir.new $labelMessages(newDir)
-
- # Entrada de solo lectura para el directorio actual.
- set ldir [label $fdir.label -text "$labelDialogs(current): "]
- set fileselect(dirEnt) [label $fdir.entry -relief sunken -width 35 \
- -bg $getleftOptions(bg) -fg $getleftOptions(fg) -anchor w]
- pack $ldir $fdir.entry -side left
- pack $fdir.arriba $fdir.new -side left -padx 5
- pack $fdir -side top -fill x -pady 5
-
- # listbox para ver el contenido del directorio.
-
- set lista [frame $t.lista]
- listbox $lista.list -yscrollcommand [list $lista.scroll set] \
- -bg $getleftOptions(bg) -fg $getleftOptions(fg) -height 10
- scrollbar $lista.scroll -command [list $lista.list yview]
- pack $lista.list -side left -fill x -expand true -padx 3
- pack $lista.scroll -side left -fill y
- pack $lista -side top -fill x -expand true -pady 3
-
- # entry para el nombre del fichero a cargar
- # el valor se guarda en fileselect(path)
- frame $t.top
- label $t.top.l -text "$labelDialogs(dir): " -padx 0
- set e [menuEntry::menuEntry $t.top.path -relief sunken \
- -fg $getleftOptions(fg) -width 27 -bg $getleftOptions(bg) \
- -textvariable Dialogos::fileselect(path)]
- pack $t.top -side top -fill x
- pack $t.top.l -side left
- pack $t.top.path -side left
- set fileselect(pathEnt) $e
-
- # Set up bindings to invoke OK and Cancel
- bind $e <Return> {
- if {[Dialogos::fileselectOK]==1} {
- set Dialogos::fileselect(done) 1
- }
- }
- bind $e <Control-c> Dialogos::fileselectCancel
- focus $e
-
- #Botones de Abrir y cancelar
-
- underButton::UnderButton $t.top.ok -buttontype button -width 10 \
- -textvariable labelButtons(select) -under $indexButtons(select) \
- -command {
- if {[Dialogos::fileselectOK]==1} {
- set Dialogos::fileselect(done) 1
- }
- }
- pack $t.top.ok -side right
-
- frame $t.cancel
- underButton::UnderButton $t.cancel.cancelar -buttontype button -width 10 \
- -textvariable labelButtons(cancel) -under $indexButtons(cancel) \
- -command {set Dialogos::fileselect(done) 0}
- pack $t.cancel.cancelar -side right
- pack $t.cancel -side bottom -fill x
- wm protocol $t WM_DELETE_WINDOW "$t.cancel.cancelar invoke"
-
- # A single click to listbox so the user can use arrow keys
- bind $e <Tab> "focus $t.lista.list ; list select set 0 ; break"
- bind $t.lista.list <Return> "Dialogos::fileselectTmp ; break"
- bind $t.lista.list <KP_Enter> "Dialogos::fileselectTmp ; break"
- bind $t.lista.list <space> "Dialogos::fileselectTake ; break"
- bind $t.lista.list <Tab> "focus $t.top.ok ; break"
- bind $t.lista.list <Button-1> {focus %W}
- bind $t.lista.list <Double-Button-1> {Dialogos::fileselectTmp ; break }
- bind $t <KeyPress-Prior> "$lista.list yview scroll -1 pages;break"
- bind $t <KeyPress-Next> "$lista.list yview scroll 1 pages;break"
- bind $t.top.ok <Tab> "focus $t.cancel.cancelar ; break"
- bind $t.cancel.cancelar <Tab> "focus $e ; break"
- bind $t <Escape> "$t.cancel.cancelar invoke"
-
- # Inicializar las variables
-
- set fileselect(path) {}
- if {($initialDir!="")&&([file exists $initialDir])} {
- set dir $initialDir
- } else {
- set dir $env(HOME)
- }
-
- set fileselect(dir) {}
- set fileselect(done) 0
-
- # Wait for the listbox to be visible so
- # we can provide feedback during the listing
- tkwait visibility .fileselect.lista.list
- fileselectList $dir
-
- grab .fileselect
- tkwait variable Dialogos::fileselect(done)
- grab release .fileselect
-
- destroy .fileselect
- update
- if {$fileselect(done)==1} {
- return $fileselect(path)
- }
- return
- }
-
- ###############################################################################
- # NewDir
- # Opens a dialog box to create a new directory.
- ###############################################################################
- proc NewDir {} {
- variable fileselect
- global labelTitles labelButtons getleftOptions
- variable done
-
- set coord(x) [winfo rootx .fileselect]
- set coord(y) [winfo rooty .fileselect]
-
- set dialog [toplevel .dialog]
- wm title $dialog $labelTitles(newDir)
- wm resizable $dialog 0 0
- wm geometry $dialog +[expr {$coord(x)+100}]+[expr {$coord(y)+15}]
-
- set done 0
-
- set marcoEx [frame $dialog.marcoEx]
- set marco [frame $marcoEx.marco -bd 2 -relief groove]
- set marcoIn [frame $marco.marcoIn]
- set dirEnt [entry $marcoIn.dirent -relief sunken -fg $getleftOptions(fg) \
- -bg $getleftOptions(bg) -width 25]
-
- set botones [frame $dialog.botones]
- set aceptar [button $botones.aceptar -textvariable labelButtons(ok) \
- -width 8 -command {set Dialogos::done 1}]
- set cancelar [button $botones.cancelar -textvariable labelButtons(cancel) \
- -width 8 -command {set Dialogos::done 0}]
-
- pack $cancelar -side right -padx 9 -pady 5
- pack $aceptar -side right -pady 5
- pack $botones -side bottom -fill x
-
- pack $dirEnt
- pack $marcoIn -padx 10 -pady 10
- pack $marco -side bottom
- pack $marcoEx -ipadx 10 -ipady 5
-
- bind $dialog <Escape> "$cancelar invoke"
- bind $dialog <Return> "$aceptar invoke"
-
- focus $dirEnt
- grab $dialog
- tkwait variable Dialogos::done
-
- if {$done==1} {
- set dir [$dirEnt get]
- if {$dir!=""} {
- if {[catch {file mkdir [file join $fileselect(dir) $dir]} error]} {
- tk_messageBox -title $labelTitles(error) -icon error \
- -message $error
- } else {
- Dialogos::fileselectList $fileselect(dir)
- }
- }
- }
- grab release $dialog
- destroy $dialog
- return
- }
-
- ###############################################################################
- # fileselectList
- # Puts into the dialog box the directories found in the current one.
- #
- # Parameter
- # dir: Current directory.
- ##############################################################################
- proc fileselectList {dir} {
- variable fileselect
-
- # Update directory
- $fileselect(dirEnt) configure -text [file nativename $dir]
-
- # Give the user some feedback
- set fileselect(dir) $dir
- .fileselect.lista.list delete 0 end
- .fileselect.lista.list insert 0 Searching...
- update idletasks
-
- .fileselect.lista.list delete 0
-
- # Add father directory and scan the current one
- if {!([regexp {^((.:)?(/))$} $fileselect(dir)])} {
- .fileselect.lista.list insert end ..
- } else {
- .fileselect.lista.list insert end /
- }
- set ficheros [glob -nocomplain $fileselect(dir)/*/]
-
- # Show results
- foreach f [lsort -dictionary $ficheros] {
- .fileselect.lista.list insert end [file tail $f]
- }
- return
- }
-
- ###############################################################################
- # fileselectOk
- # This procedure is invoked when a directory is selected, if needed it asks
- # whether the user wants to create it.
- ##############################################################################
- proc fileselectOK { } {
- variable fileselect
- global labelTitles labelMessages
-
- if {$fileselect(path)==""} {
- fileselectTake
- if {$fileselect(path)==""} return
- if {[fileselectOK]==1} {
- set fileselect(done) 1
- }
- return
- }
-
- # El directorio padre tiene tratamiento especial
- if {[regexp {\.\./?} $fileselect(path)]} {
- set fileselect(path) {}
- fileselectList [file dirname $fileselect(dir)]
- return
- }
-
- set path [file join $fileselect(dir) $fileselect(path)]
-
- if {![file exists $path]} {
- set decision [tk_messageBox -icon question \
- -message $labelMessages(unknown) -title $labelTitles(unknown) \
- -parent .fileselect -type yesno]
- switch $decision {
- yes {
- file mkdir $path
- set fileselect(path) $path
- set fileselect(done) 1
- return
- }
- no return
- }
- }
- if {[file isdirectory $path]} {
- set fileselect(done) 1
- set fileselect(path) $path
- }
- return
- }
-
- ###############################################################################
- # fileselectCancel
- # Procedure to cancel the selection
- ##############################################################################
- proc fileselectCancel {} {
- variable fileselect
-
- set fileselect(done) 1
- set fileselect(path) {}
-
- return
- }
-
- ###############################################################################
- # fileselectClick
- # Select the clicked item in the directory list.
- #
- # Parameter
- # y: point where the user clicked.
- ##############################################################################
- proc fileselectClick { y } {
- variable fileselect
-
- set l .fileselect.lista.list
- set fileselect(path) [$l get [$l nearest $Y]]
- focus $fileselect(pathEnt)
-
- return
- }
-
- ###############################################################################
- # fileselectTake
- # Takes the selected item from the directory list and puts it in the
- # path entry.
- ##############################################################################
- proc fileselectTake {} {
- variable fileselect
-
- set l .fileselect.lista.list
- set seleccion [$l curselection]
- if {$seleccion!=""} {
- set fileselect(path) [$l get $seleccion]
- }
- focus $fileselect(pathEnt)
-
- return
- }
-
- ###############################################################################
- # fileselectTmp
- # Invoked when the user doubleclicks on an item in the directory list,
- # takes the directory and makes it the current one.
- ##############################################################################
- proc fileselectTmp {} {
- variable fileselect
-
- fileselectTake
- if {[string match \.\. $fileselect(path)] } {
- fileselectList [file dirname $fileselect(dir)]
- } else {
- fileselectList [file join $fileselect(dir) $fileselect(path)]
- }
- set fileselect(path) ""
-
- return
- }
- }
-